/*
 * OgreMax Sample Viewer and Scene Loader - Ogre3D-based viewer and code for loading and displaying .scene files
 * Copyright 2010 AND Entertainment
 *
 * This code is available under the OgreMax Free License:
 *   -You may use this code for any purpose, commercial or non-commercial.
 *   -If distributing derived works (that use this source code) in binary or source code form, 
 *    you must give the following credit in your work's end-user documentation: 
 *        "Portions of this work provided by OgreMax (www.ogremax.com)"
 *
 * AND Entertainment assumes no responsibility for any harm caused by using this code.
 * 
 * The OgreMax Sample Viewer and Scene Loader were released at www.ogremax.com 
 */


#ifndef OgreMax_Mouse_INCLUDED
#define OgreMax_Mouse_INCLUDED


//Includes---------------------------------------------------------------------
#include <OIS.h>
#include "InputSource.hpp"


//Classes----------------------------------------------------------------------
namespace OgreMax
{
    /**
     * Wrapper for a mouse device
     * All public methods are safe to call with a null device
     */
    class CPPXOIS_API Mouse
    {
        friend class InputSystem;

        enum {
            BUTTON_COUNT = 8
        };

        OIS::Mouse* mouse;
        OIS::MouseState previousMouseState;
        bool updatedOnce;

    public:
        enum Axis_t {
            AXIS_X,
            AXIS_Y,
            AXIS_Z,
            AXIS_COUNT
        };

        bool IsNull             () const;

        bool PressedButton      (OIS::MouseButtonID button) const;
        bool PressingButton     (OIS::MouseButtonID button) const;
        bool ReleasedButton     (OIS::MouseButtonID button) const;

        bool PressedAnyButton   () const;
        bool PressingAnyButton  () const;
        bool ReleasedAnyButton  () const;

        bool PressedAxis        (Axis_t axis, int direction = 0) const;
        bool PressingAxis       (Axis_t axis, int direction = 0) const;
        bool ReleasedAxis       (Axis_t axis, int direction = 0) const;

        bool PressedAnyAxis     () const;
        bool PressingAnyAxis    () const;
        bool ReleasedAnyAxis    () const;

        int GetPressedButton    () const;
        int GetPressingButton   () const;
        int GetReleasedButton   () const;

        bool GetPressedAxisIndexAndDirection (int& index, int& direction) const;
        bool GetPressingAxisIndexAndDirection(int& index, int& direction) const;
        bool GetReleasedAxisIndexAndDirection(int& index, int& direction) const;

        void GetPressedButtons  (InputSourceVector& inputSources) const;
        void GetPressingButtons (InputSourceVector& inputSources) const;
        void GetReleasedButtons (InputSourceVector& inputSources) const;

        void GetPressedAxisIndicesAndDirections (InputSourceVector& inputSources) const;
        void GetPressingAxisIndicesAndDirections(InputSourceVector& inputSources) const;
        void GetReleasedAxisIndicesAndDirections(InputSourceVector& inputSources) const;

        /**
         * Determines if the mouse has moved since the last Update(), using the
         * conventional notion of the X/Y axes indicating mouse movement
         */
        bool Moved() const;

        OIS::Mouse* GetMouse();

        /** Gets the specified axis */
        const OIS::Axis& GetAxis(Axis_t axis) const;

    private:
        Mouse();

        void Set(OIS::Mouse* mouse);
        void Update();

    private:
        static const OIS::Axis& GetMouseAxis(const OIS::MouseState& mouseState, Axis_t axis);
        static bool AxisActive(int value, int direction = 0, int deadZone = 0);
    };

}

#endif